#pragma once

#include <string>

#define DCC_CREATE_PARAM_TYPE		std::string
#define DCC_CREATE_PARAM_NAME		_strLocalPath
#define DCC_CREATE_PARAM		DCC_CREATE_PARAM_TYPE DCC_CREATE_PARAM_NAME

#define DCC_REGISTER_CLASS(_CLASS) \
public: \
	static CDCRunClass ms_cls##_CLASS; \
	static CDCBase* _stdcall _CreateClass(DCC_CREATE_PARAM); \
	static void _stdcall _DeleteClass(CDCBase* pClass);

#define DCC_REGISTERING_CLASS(_CLASS) \
	CDCRunClass _CLASS::ms_cls##_CLASS = \
		{"cls_"#_CLASS, _CLASS::_CreateClass, _CLASS::_DeleteClass, NULL}; \
	SDCRunClassSave g_rcs##_CLASS(&_CLASS::ms_cls##_CLASS); \
	CDCBase* _CLASS::_CreateClass(DCC_CREATE_PARAM) {return new _CLASS(DCC_CREATE_PARAM_NAME);} \
	void _CLASS::_DeleteClass(CDCBase* pClass) {if(pClass != NULL) delete (_CLASS*)pClass;}

#define DCC_LOADING_CLASS(_CLASS, DCC_CREATE_PARAM_NAME) \
	((CDCRunClass::Load("cls_"#_CLASS) == NULL) ? NULL : \
	(_CLASS*)(CDCRunClass::Load("cls_"#_CLASS)->CreateClass(DCC_CREATE_PARAM_NAME)))

#define DCC_LOADING_CLASS_BYNAME(_szClass, DCC_CREATE_PARAM_NAME) \
	((CDCRunClass::Load("cls_C"##_szClass) == NULL) ? NULL : \
	CDCRunClass::Load("cls_C"##_szClass)->CreateClass(DCC_CREATE_PARAM_NAME))

#define DCC_RELEASING_CLASS(_CLASS, _pClass) \
	((CDCRunClass::Load("cls_"#_CLASS) == NULL) ? NULL : \
	CDCRunClass::Load("cls_"#_CLASS)->DeleteClass(_pClass))

#define DCC_RELEASING_CLASS_BYNAME(_szClass, _pClass) \
	((CDCRunClass::Load("cls_"##_szClass) == NULL) ? NULL : \
	CDCRunClass::Load("cls_"##_szClass)->DeleteClass(_pClass))
	
#define DCC_CLASS_COUNT		CDCRunClass::ms_nCount

#define DCC_CLASS_NAME(_nID)	CDCRunClass::GetClassName(_nID)

class CDCBase
{
};

class CDCRunClass
{
public:
	char*			m_pszClassName;
	CDCBase*		(_stdcall* m_pfCreateClass)(DCC_CREATE_PARAM);
	void			(_stdcall* m_pfDeleteClass)(CDCBase* pClass);
	CDCRunClass*		m_pclsPrev;

	static CDCRunClass*	ms_pclsEnd;
	static unsigned int	ms_nCount;
	static CDCRunClass*	Load(const char* pszClassName);
	static const char*	GetClassName(int nID);

	CDCBase*		CreateClass(DCC_CREATE_PARAM);
	void			DeleteClass(CDCBase* pClass);
};

struct SDCRunClassSave
{
	SDCRunClassSave(CDCRunClass* pNewClass);
};